package com.example.steriousfx.controller;

import cn.yeziji.http.tools.MRequest;
import com.alibaba.fastjson.JSONObject;
import com.example.steriousfx.component.AlertComponent;
import com.example.steriousfx.component.LoadingProgressComponent;
import com.example.steriousfx.entity.ParsingResultEntity;
import com.example.steriousfx.utils.*;
import com.example.steriousfx.utils.entity.UrlParsingResult;
import de.felixroske.jfxsupport.FXMLController;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.concurrent.Task;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.*;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.media.Media;
import javafx.scene.media.MediaPlayer;
import javafx.scene.media.MediaView;
import javafx.scene.text.Text;
import javafx.stage.FileChooser;
import javafx.stage.Stage;
import javafx.util.Duration;
import org.apache.http.client.methods.HttpPost;

import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 首页控制器
 *
 * @author gzkemays
 * @since 2021/10/17 13:48
 */
@FXMLController
public class IndexController implements Initializable {
  @FXML private Slider volSlider;
  @FXML private Slider videoSlider;
  @FXML private Button playVideoBtn;
  @FXML private RadioButton redirectUrlRadio;
  @FXML private MediaView mediaVideo;
  @FXML private CheckBox emptyIgnore;
  @FXML private TextArea textContent;
  @FXML private Button staticsLenBtn;
  @FXML private TextField textLength;

  @FXML private TextField originUrl;
  @FXML private TextField shortUrl;
  @FXML private Button shortUrlBtn;
  @FXML private Button getCurrentTimeBtn;
  @FXML private TextField currentMillis;
  @FXML private TextField currentSecond;
  @FXML private TextField digitPwdField;
  @FXML private TextField pwdGenerateField;
  @FXML private TextField timestampTextField;
  @FXML private TextField timeFormatTextField;
  @FXML private Button timeFormatBtn;
  @FXML private Text timestampCompany;
  @FXML private TextField titleField;
  @FXML private TextField pwdField;
  @FXML private TextField urlField;
  @FXML private TextArea oldAreaField;
  @FXML private TextArea transAreaField;
  @FXML private TextArea formatArea;
  @FXML private TextArea formatResultArea;
  @FXML private ComboBox<String> languageCombo;
  @FXML private Button transBtn;
  @FXML private RadioButton openTread;
  @FXML private RadioButton openCompression;
  @FXML private CheckBox checkCells;
  @FXML private ImageView image;
  @FXML private SplitPane splitPane;
  @FXML private TableView<ParsingResultEntity> tableView;
  @FXML private TableColumn<ParsingResultEntity, String> url;
  @FXML private TableColumn<ParsingResultEntity, String> type;
  @FXML private TableColumn<ParsingResultEntity, CheckBox> checkBoxColumn;
  @FXML private Button parseBtn;
  @FXML private Button downloadBtn;
  @FXML private Button parseCodeBtn;
  private Stage stage;
  private Boolean goLocation = true;
  private static final String BAI_DU_TRANSITION_APPID = "20211019000977449";
  private static final String BAI_DU_TRANSITION_SECRET = "dOvYh6lb7edFp6McgvVG";
  private static final String ZH_CN_KEY = "中文";
  private static final String EN_CN_KEY = "英文";
  private static final String NUMBER_MATCHER = "[0-9]+";
  private static final Integer GENERATOR_PWD_MAX_LENGTH = 3;
  private Pattern emptyPattern = Pattern.compile("\\s*|\t|\r|\n");
  MediaPlayer mediaPlayer = null;

  DownloadSourceUtils downloadSourceUtils = new DownloadSourceUtils();
  TransitionUtils transitionUtils =
      TransitionUtils.create(BAI_DU_TRANSITION_APPID, BAI_DU_TRANSITION_SECRET);

  @Override
  public void initialize(URL location, ResourceBundle resources) {
    // image 的默认图片
    image.setImage(new Image(String.valueOf(getClass().getResource("/images/yzj_icon3.png"))));
    // 提供默认值作为案例
    ObservableList<ParsingResultEntity> entities =
        FXCollections.observableArrayList(
            new ParsingResultEntity("示例地址", "数据类型示例"),
            new ParsingResultEntity("http://img.yeziji.xyz/yzj-di.png", "图片"),
            new ParsingResultEntity("www.bing.com", "地址"));
    // 设置可编辑
    tableView.setEditable(true);
    // 设置 table 的 row 工厂
    tableView.setRowFactory(
        column -> {
          TableRow<ParsingResultEntity> row = new TableRow<>();
          row.setOnMouseClicked(
              event -> {
                if (event.getClickCount() == 1 && (!row.isEmpty())) {
                  ParsingResultEntity item = row.getItem();
                  try {
                    image.setImage(new Image(item.getUrl(), 319.0, 232.0, true, true));
                  } catch (Exception e) {
                    AlertComponent.exceptionErrorArea(e, "如果确保选中的数据类型是“图片”依然报错，请将以下日志给开发者看看。");
                  }
                }
              });
          return row;
        });
    url.setCellValueFactory(cell -> new SimpleStringProperty(cell.getValue().getUrl()));
    type.setCellValueFactory(cell -> new SimpleStringProperty(cell.getValue().getType()));
    // 绑定为 checkBox
    checkBoxColumn.setCellValueFactory(
        cell -> cell.getValue().getCheckBoxComponent().getCheckBox());
    // 传入默认值
    tableView.setItems(entities);
    // 定义输入框输入监听
    ChangeListener<String> urlListener =
        (observable, oldValue, newValue) -> {
          if (goLocation) {
            String val = newValue.trim();
            boolean isHttp = val.contains("http://") || val.contains("https://");
            boolean isLongUri = val.length() > 15;
            if (isHttp && isLongUri) {
              String locationUrl = null;
              try {
                if (redirectUrlRadio.isSelected()) {
                  locationUrl = downloadSourceUtils.getLocationUrl(newValue);
                }
              } catch (IOException e) {
                e.printStackTrace();
              }
              if (locationUrl != null) {
                String urlsPassword = downloadSourceUtils.getUrlsPassword(locationUrl);
                goLocation = false;
                pwdField.setText(urlsPassword);
                urlField.setText(locationUrl);
              }
            }
          }
        };
    urlField.textProperty().addListener(urlListener);
    // 插入选中
    languageCombo
        .getItems()
        .addAll(
            FXCollections.observableList(
                new ArrayList<String>() {
                  {
                    add("中文");
                    add("英文");
                  }
                }));
    oldAreaField.setWrapText(true);
    transAreaField.setWrapText(true);
    formatArea.setWrapText(true);
    formatResultArea.setWrapText(true);
    playVideoBtn.setVisible(false);
    videoSlider.setVisible(false);
    volSlider.setVisible(false);
    // 监听翻译文本的输入
    //    ChangeListener<String> transitionListener =
    //        (observable, oldValue, newValue) -> {
    //          if (StrUtils.isContainChinese(newValue)) {
    //            languageCombo.setValue(EN_CN_KEY);
    //          } else {
    //            languageCombo.setValue(ZH_CN_KEY);
    //          }
    //        };
    //    oldAreaField.textProperty().addListener(transitionListener);

    // UI 高频更新避免 null 异常
    /*    Platform.runLater(
    () ->
        new Timer()
            .schedule(
                new TimerTask() {
                  @Override
                  public void run() {
                    try {
                      currentMillis.setText(String.valueOf(DateUtils.getMillis()));
                      currentSecond.setText(String.valueOf(DateUtils.getSeconds()));
                    } catch (Exception e) {
                      e.printStackTrace();
                    }
                  }
                },
                0,
                5L * 1000));*/

  }

  public void download(ActionEvent actionEvent) {
    LoadingProgressComponent component = new LoadingProgressComponent(stage, "保存中...");
    component.activateProgressBar(
        new Task<Boolean>() {
          @Override
          protected Boolean call() throws Exception {
            if (redirectUrlRadio.isSelected()) {
              downloadSourceUtils.packageSourceZip(urlField.getText(), pwdField.getText());
            } else {
              System.out.println("downloadVideo");
              downloadSourceUtils.packageFile(
                  new UrlParsingResult(urlField.getText(), StrUtils.createRandomStr(5), ".mp4"));
            }
            return true;
          }
        },
        () -> {});
    resetField();
  }

  public void parsing(ActionEvent actionEvent) throws IOException {
    String text = urlField.getText();
    boolean isHttp = text.contains("http://") || text.contains("https://");
    if (!isHttp) {
      AlertComponent.normalErrorTips("请输入正确的地址");
    } else {
      UrlParsingResult urlsList =
          downloadSourceUtils.getUrlsList(urlField.getText(), pwdField.getText());
      titleField.setText(urlsList.getTitle());
      setTableViewCells(urlsList);
    }
  }

  public void openCode(ActionEvent actionEvent) {
    FileChooser fileChooser = new FileChooser();
    fileChooser.setInitialDirectory(new File("D:\\TempSave\\图片存根\\QQWEB"));
    fileChooser
        .getExtensionFilters()
        .addAll(
            new FileChooser.ExtensionFilter("JPG", "*.jpg"),
            new FileChooser.ExtensionFilter("PNG", "*.png"));
    File file = fileChooser.showOpenDialog(stage);
    LoadingProgressComponent component = new LoadingProgressComponent(stage, "解析地址与密码...");
    component.activateProgressBar(
        new Task<Boolean>() {
          @Override
          protected Boolean call() throws Exception {
            if (file != null) {
              String url = QRCodeUtils.decode(file);
              urlField.setText(url);
              if (redirectUrlRadio.isSelected()) {
                String locationUrl = downloadSourceUtils.getLocationUrl(url);
                String urlsPassword = downloadSourceUtils.getUrlsPassword(locationUrl);
                urlField.setText(locationUrl);
                pwdField.setText(urlsPassword);
                UrlParsingResult urlsList =
                    downloadSourceUtils.getUrlsList(locationUrl, urlsPassword);
                titleField.setText(urlsList.getTitle());
                setTableViewCells(urlsList);
              } else {
                if (mediaPlayer != null) {
                  mediaPlayer.dispose();
                }
                Media media = new Media(url);
                mediaPlayer = new MediaPlayer(media);
                mediaPlayer.setAutoPlay(false);
                mediaVideo.setMediaPlayer(mediaPlayer);
                /*                mediaVideo.setFitWidth(365);
                mediaVideo.setFitHeight(180);*/
                // 初始化
                mediaPlayer.setOnReady(
                    () -> {
                      Duration cycleDuration = mediaPlayer.getTotalDuration();
                      videoSlider.setMax(cycleDuration.toSeconds());
                      playVideoBtn.setVisible(true);
                      videoSlider.setVisible(true);
                      volSlider.setVisible(true);
                      mediaPlayer.setVolume(volSlider.getValue());
                    });
                volSlider
                    .valueProperty()
                    .addListener(
                        new ChangeListener<Number>() {
                          @Override
                          public void changed(
                              ObservableValue<? extends Number> observable,
                              Number oldValue,
                              Number newValue) {
                            mediaPlayer.setVolume(newValue.doubleValue() / 100);
                          }
                        });
                // 监听当前时间
                mediaPlayer
                    .currentTimeProperty()
                    .addListener(
                        (observable, oldValue, newValue) ->
                            videoSlider.setValue(newValue.toSeconds()));
                // 监听鼠标点击进度条
                videoSlider.setOnMousePressed(
                    event -> {
                      mediaPlayer.pause();
                    });
                // 监听鼠标释放进度条
                videoSlider.setOnMouseReleased(
                    event -> {
                      mediaPlayer.seek(Duration.seconds(videoSlider.getValue()));
                      mediaPlayer.play();
                    });
                playVideoBtn.setOnAction(
                    e -> {
                      if (">".equals(playVideoBtn.getText())) {
                        mediaPlayer.play();
                        playVideoBtn.setText("||");
                      } else {
                        mediaPlayer.pause();
                        playVideoBtn.setText(">");
                      }
                    });
              }
            }
            return true;
          }
        },
        () -> {});
  }

  public void checkAll(ActionEvent actionEvent) {
    boolean selected = checkCells.isSelected();
    ObservableList<ParsingResultEntity> items = tableView.getItems();
    if (selected) {
      for (ParsingResultEntity item : items) {
        item.getCheckBoxComponent().getSelected();
      }
    } else {
      for (ParsingResultEntity item : items) {
        item.getCheckBoxComponent().noSelected();
      }
    }
  }

  private void resetField() {
    goLocation = true;
  }

  private void setTableViewCells(UrlParsingResult result) {
    List<String> urls = result.getUrls();
    ObservableList<ParsingResultEntity> observableList = FXCollections.observableArrayList();
    for (String picUrl : urls) {
      observableList.add(new ParsingResultEntity(picUrl, "图片"));
    }
    tableView.setItems(observableList);
    resetField();
  }

  /** 翻译 */
  public void transition(ActionEvent actionEvent) {
    String value = languageCombo.getValue();
    String text = oldAreaField.getText();
    if (StrUtils.isContainChinese(text)) {
      languageCombo.setValue(EN_CN_KEY);
      transAreaField.setText(transitionUtils.to("en").transition(oldAreaField.getText()));
    } else {
      languageCombo.setValue(ZH_CN_KEY);

      transAreaField.setText(transitionUtils.to("zh").transition(oldAreaField.getText()));
    }
  }

  public void format(ActionEvent actionEvent) {
    String text = formatArea.getText();
    if (!JsonUtils.isJson(text)) {
      AlertComponent.normalErrorTips("该字符串不是 JSON 字符串");
    } else {
      formatResultArea.setText(JsonUtils.jsonFormat(text));
    }
  }

  public void generatePwd(ActionEvent actionEvent) {
    String length = digitPwdField.getText();
    if (!length.matches(NUMBER_MATCHER)) {
      AlertComponent.normalErrorTips("只能指定纯数字位数");
    }
    if (length.length() > GENERATOR_PWD_MAX_LENGTH) {
      AlertComponent.normalErrorTips("指定位数过长");
    } else {
      String randomStr = StrUtils.createRandomStr(Integer.parseInt(length));
      pwdGenerateField.setText(randomStr);
    }
  }

  public void timestampFormat(ActionEvent actionEvent) {
    String text = timestampTextField.getText();
    if (text.matches(NUMBER_MATCHER)) {
      if (text.length() == DateUtils.MILLIS_LENGTH) {
        timestampCompany.setText("秒");
      } else {
        timestampCompany.setText("毫秒");
      }
      long number = Long.parseLong(text);
      timeFormatTextField.setText(DateUtils.getTimestampData(number));
    }
  }

  public void generateUrl(ActionEvent actionEvent) {
    String url = "http://open.yeziji.xyz/openapi/shortUrl";
    Map<Object, Object> data = new HashMap<>();
    data.put("url", originUrl.getText().trim());
    try {
      HttpPost post = MRequest.getUrlEncodedFormPost(url, data);
      String resultFromRequest = MRequest.getResultFromRequest(post);
      if (cn.yeziji.utils.JsonUtils.isJson(resultFromRequest)) {
        JSONObject jsonObject = JSONObject.parseObject(resultFromRequest);
        if (jsonObject.getInteger("code").equals(0)) {
          shortUrl.setText(jsonObject.getString("data"));
        }
      }
    } catch (Exception e) {
      e.printStackTrace();
    }
  }

  public void getCurrentTimeTimestamp(ActionEvent actionEvent) {
    currentMillis.setText(String.valueOf(DateUtils.getMillis()));
    currentSecond.setText(String.valueOf(DateUtils.getSeconds()));
  }

  public void staticsContent(ActionEvent actionEvent) {
    String text = textContent.getText();
    if (emptyIgnore.isSelected()) {
      Matcher m = emptyPattern.matcher(text);
      text = m.replaceAll("");
      textLength.setText(String.valueOf(text.trim().length()));
    } else {
      textLength.setText(String.valueOf(text.length()));
    }
  }
}
